/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.spice.im.utils;

import android.content.Context;





import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
//import android.os.AsyncTask;
//import android.os.AsyncTask.Status;
import android.os.Handler;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;

//import org.jivesoftware.smack.util.StringUtils;
//import org.jivesoftware.smackx.packet.VCard;

import com.dodowaterfall.widget.FlowView;
//import com.example.android.bitmapfun.util.AsyncTask.Status;
//import com.stb.isharemessage.service.XmppConnectionAdapter;
//import com.stb.isharemessage.ui.RoundImageView;
//import com.speed.im.RoundImageView;
//import com.stb.isharemessage.utils.PhotoUtils;
//import com.speed.im.utils.AsyncTask;
//import com.speed.im.utils.AsyncTask.Status;
//import com.huewu.pla.sample.BuildConfig;
import com.spice.im.RoundImageView;
import com.spice.im.utils.AsyncTask.Status;

/**
 * This class wraps up completing some arbitrary long running work when loading
 * a bitmap to an ImageView. It handles things like using a memory and disk
 * cache, running the work in a background thread and setting a placeholder
 * image.
 */
public abstract class ImageWorker {
//	private XmppConnectionAdapter xmppConnectionAdapter = null;
	private boolean isVcard = false;
//	private VCard vcard = null;
	private byte[] retbAvator = null;
	
	
	private int uListype = 0;//0��ͨͼƬlistview 1�ٲ���  2��ͼģʽ
	public void setUListype(int ulistype){
		this.uListype = ulistype;
	}
	private static final String TAG = "ImageWorker";
	private static final int FADE_IN_TIME = 200;

	private ImageCache mImageCache;
	private Bitmap mLoadingBitmap;
	private boolean mFadeInBitmap = true;
	private boolean mExitTasksEarly = false;

	protected Context mContext;
	protected ImageWorkerAdapter mImageWorkerAdapter;
	
	
//	private Executor mExecutor = new Executor();
	BitmapWorkerTask task = null;

	protected ImageWorker(Context context) {
		mContext = context;
//		mExecutor.start();
	}

//	private static final BlockingQueue<BitmapWorkerTask> mTasks = new LinkedBlockingQueue<BitmapWorkerTask>();
//	// ͨ���ź�������ͬʱִ�е��߳���
//	Semaphore mSemaphore = new Semaphore(50);
//
//	// ���������������ߣ�ȥ�������ȡ����������Ȼ��ִ�У���û�������ʱ������߾͵ȴ�?
//	class Executor extends Thread {
//		@Override
//		public void run() {
//			while (true) {
//				BitmapWorkerTask task = null;
//				try {
//					task = mTasks.take();
//					if (task != null) {
//						mSemaphore.acquire();
//						task.execute();
//						
//					}
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//			}
//		}
//	}
	
	private static ExecutorService LIMITED_TASK_EXECUTOR;  
    static {
        LIMITED_TASK_EXECUTOR = (ExecutorService) Executors.newFixedThreadPool(7);  
    }; 
	protected List<AsyncTask<Object, Void, Bitmap>> mAsyncTasks = new ArrayList<AsyncTask<Object, Void, Bitmap>>();	
	protected void putAsyncTask(AsyncTask<Object, Void, Bitmap> asyncTask,Object data) {
		mAsyncTasks.add(asyncTask.executeOnExecutor(LIMITED_TASK_EXECUTOR, data));//LIMITED_TASK_EXECUTOR  FULL_TASK_EXECUTOR
//		mAsyncTasks.add(asyncTask.execute());
	}
	protected void clearAsyncTask() {
		Iterator<AsyncTask<Object, Void, Bitmap>> iterator = mAsyncTasks.iterator();
		while (iterator.hasNext()) {
			AsyncTask<Object, Void, Bitmap> asyncTask = iterator.next();
			if (asyncTask != null && !asyncTask.isCancelled()) {
				asyncTask.cancel(true);
			}
		}
		mAsyncTasks.clear();
	}
	
	public void onCancel() {
		clearAsyncTask();
	}
	/**
	 * Load an image specified by the data parameter into an ImageView (override
	 * {@link ImageWorker#processBitmap(Object)} to define the processing
	 * logic). A memory and disk cache will be used if an {@link ImageCache} has
	 * been set using {@link ImageWorker#setImageCache(ImageCache)}. If the
	 * image is found in the memory cache, it is set immediately, otherwise an
	 * {@link AsyncTask} will be created to asynchronously load the bitmap.
	 * 
	 * @param data
	 *            The URL of the image to download.
	 * @param imageView
	 *            The ImageView to bind the downloaded image to.
	 */
	public void loadImage(Object data, FlowView imageView) {
		Bitmap bitmap = null;
		BitmapDrawable bd = null;

		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCache(String.valueOf(data));
		}

		if (bitmap != null) {
			// Bitmap found in memory cache
			imageView.setImageBitmap(bitmap);
		} else if (cancelPotentialWork(data, imageView)) {
			if(task == null || task.getStatus() != Status.RUNNING)
			try{
				final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
//				task = new BitmapWorkerTask(imageView);
	//			final BitmapWorkerTask task = new BitmapWorkerTask(imageView,data);
				final AsyncDrawable asyncDrawable = new AsyncDrawable(mContext.getResources(), mLoadingBitmap, task);
				imageView.setImageDrawable(asyncDrawable);
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				
				
//				task.execute(data);
				
				putAsyncTask(task,data);
			}catch(Exception e){
				Log.e("error", "RejectedExecutionException in content_img: " +  String.valueOf(data)+";"+e.getMessage());
			}
//			try {
//				// ��������������
//				mTasks.put(task);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
		}
	}
	
	public void loadNormalImage(Object data, ImageView imageView,int sizeType,int wid,int heig,Handler handler) {//sizeType 0 77*77 1 ʹ��wid,heig ����  Ĭ�ϴ�С
		Bitmap bitmap = null;
		BitmapDrawable bd = null;

		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCache(String.valueOf(data));
		}

		if (bitmap != null) {
			// Bitmap found in memory cache
			imageView.setImageBitmap(bitmap);
		} else if (cancelPotentialNormalImageWork(data, imageView)) {
			if(task == null || task.getStatus() != Status.RUNNING)
			try{
				final BitmapWorkerNormalImageTask task = new BitmapWorkerNormalImageTask(imageView,sizeType,wid,heig,handler);
//				task = new BitmapWorkerTask(imageView);
	//			final BitmapWorkerTask task = new BitmapWorkerTask(imageView,data);
				final AsyncDrawableNormalImage asyncDrawable = new AsyncDrawableNormalImage(mContext.getResources(), mLoadingBitmap, task);
				imageView.setImageDrawable(asyncDrawable);
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				
				
//				task.execute(data);
				
				putAsyncTask(task,data);
			}catch(Exception e){
				Log.e("error", "RejectedExecutionException in content_img: " +  String.valueOf(data)+";"+e.getMessage());
			}
//			try {
//				// ��������������
//				mTasks.put(task);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
		}
	}
	public void loadRoundImage(Object data, RoundImageView imageView,Handler handler) {
		Bitmap bitmap = null;
		BitmapDrawable bd = null;

		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCache(String.valueOf(data));
		}

		if (bitmap != null) {
			// Bitmap found in memory cache
			imageView.setImageBitmap(bitmap);
		} else if (cancelPotentialRoundImageViewWork(data, imageView)) {
			if(task == null || task.getStatus() != Status.RUNNING)
			try{
				final BitmapWorkerRoundImageViewTask task = new BitmapWorkerRoundImageViewTask(imageView,handler);
//				task = new BitmapWorkerTask(imageView);
	//			final BitmapWorkerTask task = new BitmapWorkerTask(imageView,data);
				final AsyncDrawableRoundImageView asyncDrawable = new AsyncDrawableRoundImageView(mContext.getResources(), mLoadingBitmap, task);
				imageView.setImageDrawable(asyncDrawable);
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
//				task.execute(data);
				putAsyncTask_RoundImage(task,data);
			}catch(Exception e){
				Log.e("error", "RejectedExecutionException in content_img: " +  String.valueOf(data)+";"+e.getMessage());
			}
//			try {
//				// ��������������
//				mTasks.put(task);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
		}
	}
    /**
     * Object data : username@servicename/resources
     */
	public void loadImage(boolean isVcard,Object data, FlowView imageView) {
//		if(this.xmppConnectionAdapter == null)
//		this.xmppConnectionAdapter = xmppConnectionAdapter;
		this.isVcard = isVcard;
		Bitmap bitmap = null;
		BitmapDrawable bd = null;
		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCache(String.valueOf(data));
		}

		if (bitmap != null) {
			// Bitmap found in memory cache
			imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
		} else if (cancelPotentialWork(data, imageView)) {
			if(task == null || task.getStatus() != Status.RUNNING)
			try{
				final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
//				task = new BitmapWorkerTask(imageView);
	//			final BitmapWorkerTask task = new BitmapWorkerTask(imageView,data);
				final AsyncDrawable asyncDrawable = new AsyncDrawable(mContext.getResources(), mLoadingBitmap, task);
				
//				imageView.setImageDrawable(asyncDrawable);
				bd = (BitmapDrawable) asyncDrawable;
				bitmap = bd.getBitmap();
				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				
//				task.execute(data);
				putAsyncTask(task,data);
			}catch(Exception e){
				Log.e("error", "RejectedExecutionException in content_img: " +  String.valueOf(data)+";"+e.getMessage());
			}
		}
	}
	/**
	 * Load an image specified from a set adapter into an ImageView (override
	 * {@link ImageWorker#processBitmap(Object)} to define the processing
	 * logic). A memory and disk cache will be used if an {@link ImageCache} has
	 * been set using {@link ImageWorker#setImageCache(ImageCache)}. If the
	 * image is found in the memory cache, it is set immediately, otherwise an
	 * {@link AsyncTask} will be created to asynchronously load the bitmap.
	 * {@link ImageWorker#setAdapter(ImageWorkerAdapter)} must be called before
	 * using this method.
	 * 
	 * @param data
	 *            The URL of the image to download.
	 * @param imageView
	 *            The ImageView to bind the downloaded image to.
	 */
	public void loadImage(int num, FlowView imageView) {
		if (mImageWorkerAdapter != null) {
			loadImage(mImageWorkerAdapter.getItem(num), imageView);
		} else {
			throw new NullPointerException("Data not set, must call setAdapter() first.");
		}
	}

	/**
	 * Set placeholder bitmap that shows when the the background thread is
	 * running.
	 * 
	 * @param bitmap
	 */
	public void setLoadingImage(Bitmap bitmap) {
		mLoadingBitmap = bitmap;
	}

	/**
	 * Set placeholder bitmap that shows when the the background thread is
	 * running.
	 * 
	 * @param resId
	 */
	public void setLoadingImage(int resId) {
		mLoadingBitmap = BitmapFactory.decodeResource(mContext.getResources(), resId);
	}

	/**
	 * Set the {@link ImageCache} object to use with this ImageWorker.
	 * 
	 * @param cacheCallback
	 */
	public void setImageCache(ImageCache cacheCallback) {
		mImageCache = cacheCallback;
	}

	public ImageCache getImageCache() {
		return mImageCache;
	}

	/**
	 * If set to true, the image will fade-in once it has been loaded by the
	 * background thread.
	 * 
	 * @param fadeIn
	 */
	public void setImageFadeIn(boolean fadeIn) {
		mFadeInBitmap = fadeIn;
	}

	public void setExitTasksEarly(boolean exitTasksEarly) {
		mExitTasksEarly = exitTasksEarly;
	}

	/**
	 * Subclasses should override this to define any processing or work that
	 * must happen to produce the final bitmap. This will be executed in a
	 * background thread and be long running. For example, you could resize a
	 * large bitmap here, or pull down an image from the network.
	 * 
	 * @param data
	 *            The data to identify which image to process, as provided by
	 *            {@link ImageWorker#loadImage(Object, ImageView)}
	 * @return The processed bitmap
	 */
	protected abstract Bitmap processBitmap(Object data);

	public static void cancelWork(FlowView imageView) {
		final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
		if (bitmapWorkerTask != null) {
			bitmapWorkerTask.cancel(true);
//			if (BuildConfig.DEBUG) {
//				final Object bitmapData = bitmapWorkerTask.data;
//				Log.d(TAG, "cancelWork - cancelled work for " + bitmapData);
//			}
		}
	}

	/**
	 * Returns true if the current work has been canceled or if there was no
	 * work in progress on this image view. Returns false if the work in
	 * progress deals with the same data. The work is not stopped in that case.
	 */
	public static boolean cancelPotentialWork(Object data, FlowView imageView) {
		final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

		if (bitmapWorkerTask != null) {
			final Object bitmapData = bitmapWorkerTask.data;
			if (bitmapData == null || !bitmapData.equals(data)) {
				bitmapWorkerTask.cancel(true);
//				if (BuildConfig.DEBUG) {
//					Log.d(TAG, "cancelPotentialWork - cancelled work for " + data);
//				}
			} else {
				// The same work is already in progress.
				return false;
			}
		}
		return true;
	}
	public static boolean cancelPotentialNormalImageWork(Object data, ImageView imageView) {
		final BitmapWorkerNormalImageTask bitmapWorkerTask = getBitmapWorkerNormalImageTask(imageView);

		if (bitmapWorkerTask != null) {
			final Object bitmapData = bitmapWorkerTask.data;
			if (bitmapData == null || !bitmapData.equals(data)) {
				bitmapWorkerTask.cancel(true);
//				if (BuildConfig.DEBUG) {
//					Log.d(TAG, "cancelPotentialWork - cancelled work for " + data);
//				}
			} else {
				// The same work is already in progress.
				return false;
			}
		}
		return true;
	}
	public static boolean cancelPotentialRoundImageViewWork(Object data, RoundImageView imageView) {
		final BitmapWorkerRoundImageViewTask bitmapWorkerTask = getBitmapWorkerRoundImageViewTask(imageView);

		if (bitmapWorkerTask != null) {
			final Object bitmapData = bitmapWorkerTask.data;
			if (bitmapData == null || !bitmapData.equals(data)) {
				bitmapWorkerTask.cancel(true);
//				if (BuildConfig.DEBUG) {
//					Log.d(TAG, "cancelPotentialWork - cancelled work for " + data);
//				}
			} else {
				// The same work is already in progress.
				return false;
			}
		}
		return true;
	}

	/**
	 * @param imageView
	 *            Any imageView
	 * @return Retrieve the currently active work task (if any) associated with
	 *         this imageView. null if there is no such task.
	 */
	private static BitmapWorkerTask getBitmapWorkerTask(FlowView imageView) {
		if (imageView != null) {
			final Drawable drawable = imageView.getDrawable();
			if (drawable instanceof AsyncDrawable) {
				final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
				return asyncDrawable.getBitmapWorkerTask();
			}
		}
		return null;
	}
	private static BitmapWorkerNormalImageTask getBitmapWorkerNormalImageTask(ImageView imageView) {
		if (imageView != null) {
			final Drawable drawable = imageView.getDrawable();
			if (drawable instanceof AsyncDrawableNormalImage) {
				final AsyncDrawableNormalImage asyncDrawable = (AsyncDrawableNormalImage) drawable;
				return asyncDrawable.getBitmapWorkerNormalImageTask();
			}
		}
		return null;
	}
	private static BitmapWorkerRoundImageViewTask getBitmapWorkerRoundImageViewTask(RoundImageView imageView) {
		if (imageView != null) {
			final Drawable drawable = imageView.getDrawable();
			if (drawable instanceof AsyncDrawableRoundImageView) {
				final AsyncDrawableRoundImageView asyncDrawable = (AsyncDrawableRoundImageView) drawable;
				return asyncDrawable.getBitmapWorkerTask();
			}
		}
		return null;
	}
	/**
	 * The actual AsyncTask that will asynchronously process the image.
	 */
	private class BitmapWorkerTask extends AsyncTask<Object, Void, Bitmap> {
		private Object data;
		private final WeakReference<FlowView> imageViewReference;

		public BitmapWorkerTask(FlowView imageView) {
			imageViewReference = new WeakReference<FlowView>(imageView);
		}
		
//		public BitmapWorkerTask(FlowView imageView,Object data1){
//			imageViewReference = new WeakReference<FlowView>(imageView);
//			data = data1;
//		}

		/**
		 * Background processing.
		 */
		@Override
		protected Bitmap doInBackground(Object... params) {
			data = params[0];
			final String dataString = String.valueOf(data);
			Bitmap bitmap = null;

			// If the image cache is available and this task has not been
			// cancelled by another
			// thread and the ImageView that was originally bound to this task
			// is still bound back
			// to this task and our "exit early" flag is not set then try and
			// fetch the bitmap from
			// the cache
			if (mImageCache != null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
				bitmap = mImageCache.getBitmapFromDiskCache(dataString);
			}

			// If the bitmap was not found in the cache and this task has not
			// been cancelled by
			// another thread and the ImageView that was originally bound to
			// this task is still
			// bound back to this task and our "exit early" flag is not set,
			// then call the main
			// process method (as implemented by a subclass)
			if(isVcard && dataString!=null){
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
					
			        final File cacheDir = DiskLruCache.getDiskCacheDir(mContext, ImageFetcher.HTTP_CACHE_DIR);

			        final DiskLruCache cache =
			                DiskLruCache.openCache(mContext, cacheDir, ImageFetcher.HTTP_CACHE_SIZE);
//			        if (urlString.toUpperCase().startsWith("HTTP")) {
			        Log.e("������20130901������", "���cacheDir="+cacheDir+";cache="+cache+";dataString="+dataString);
			        if(cacheDir!=null && cache!=null){
			        final File cacheFile = new File(cache.createFilePath(dataString));//�ռ䲻�� cache=null

			        if (cache.containsKey(dataString)) {
//			            if (BuildConfig.DEBUG) {
////			                Log.d(TAG, "downloadBitmap - found in http cache - " + urlString);
//			            }
			        	return BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
			        }
			        }else{
//			        	Toast.makeText(mContext, "�洢�ռ䲻��", Toast.LENGTH_SHORT).show();
			        	Log.e("������20130901ImageWorker�洢�ռ䲻�������?", "���洢�ռ䲻��");
			        }
//			        if(xmppConnectionAdapter!=null)
//			        try{
//					vcard = xmppConnectionAdapter.getOtherVCard(StringUtils.parseName(dataString));
//					if(vcard!=null){
//						retbAvator = vcard.getAvatar();
//					    if(retbAvator!=null){
////					    	Log.e("������20130827������avator=",new String(retbAvator));
//					    	bitmap = BitmapFactory.decodeByteArray(retbAvator, 0, retbAvator.length);
//					    	if(cacheDir!=null && cache!=null)
//					    	cache.put(dataString, bitmap);
//					    	return bitmap;
//					    }
//					}
//			        }catch(Exception e){
//			        	
//			        }finally{
//			        	isVcard = false;
//			        	retbAvator = null;
//			        	vcard = null;
//			        	xmppConnectionAdapter = null;
//			        	
//			        }
				}
			}else{
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {

					bitmap = processBitmap(params[0]);

				}
			}
			
//			if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
//				bitmap = processBitmap(data);
//			}

			// If the bitmap was processed and the image cache is available,
			// then add the processed
			// bitmap to the cache for future use. Note we don't check if the
			// task was cancelled
			// here, if it was, and the thread is still running, we may as well
			// add the processed
			// bitmap to our cache as it might be used again in the future
			if (bitmap != null && mImageCache != null) {
				mImageCache.addBitmapToCache(dataString, bitmap);
			}

			return bitmap;
		}

		/**
		 * Once the image is processed, associates it to the imageView
		 */
		@Override
		protected void onPostExecute(Bitmap bitmap) {
//			mSemaphore.release();
			// if cancel was called on this task or the "exit early" flag is set
			// then we're done
			if (isCancelled() || mExitTasksEarly) {
				bitmap = null;
			}

			final FlowView imageView = getAttachedImageView();
			if (bitmap != null && imageView != null) {
				
				//20130717 start
				
				int width = bitmap.getWidth();// ��ȡ��ʵ���?
				int height = bitmap.getHeight();

				LayoutParams lp = imageView.getLayoutParams();
//				if(uListype == 0){
//					lp.width = 77;//60
					lp.width = dip2px(mContext,77);
//					lp.height = 77;//60	
					lp.height = dip2px(mContext,77);
//				}else{
//				    lp.width = imageView.getItemWidth();
////					lp.height = (height * imageView.getItemWidth())
////							/ width;// ����߶�?
//					lp.height = getHeight(imageView.getItemWidth(),height,width);
//				}
				
				imageView.setLayoutParams(lp);
				//20130717 end
				
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				setImageBitmap(imageView, PhotoUtils.toRoundCorner(bitmap, 8));
			}
		}

		/**
		 * Returns the ImageView associated with this task as long as the
		 * ImageView's task still points to this task as well. Returns null
		 * otherwise.
		 */
		private FlowView getAttachedImageView() {
			final FlowView imageView = imageViewReference.get();
			final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

			if (this == bitmapWorkerTask) {
				return imageView;
			}

			return null;
		}
		
		public int getHeight(int srcViewWidth,int srcHeight,int srcWidth){
			int defHeight = 77;
			Random random = new Random();
			return (srcHeight * srcViewWidth) / srcWidth + random.nextInt(3)*10;
		}
	}

	
	/**
	 * The actual AsyncTask that will asynchronously process the image.
	 */
	private class BitmapWorkerNormalImageTask extends AsyncTask<Object, Void, Bitmap> {//Void
		private Object data;
		private final WeakReference<ImageView> imageViewReference;
		private int mSizeType;
		private int mWid;
		private int mHeig;
		private Handler handler;

		public BitmapWorkerNormalImageTask(ImageView imageView,int sizeType,int wid,int heig,Handler handler) {
			imageViewReference = new WeakReference<ImageView>(imageView);
			mSizeType = sizeType;
			mWid = wid;
			mHeig = heig;
			this.handler = handler;
		}
		
//		public BitmapWorkerTask(FlowView imageView,Object data1){
//			imageViewReference = new WeakReference<FlowView>(imageView);
//			data = data1;
//		}

		/**
		 * Background processing.
		 */
		@Override
		protected Bitmap doInBackground(Object... params) {
			data = params[0];
			final String dataString = String.valueOf(data);
			Bitmap bitmap = null;

			// If the image cache is available and this task has not been
			// cancelled by another
			// thread and the ImageView that was originally bound to this task
			// is still bound back
			// to this task and our "exit early" flag is not set then try and
			// fetch the bitmap from
			// the cache
			if (mImageCache != null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
				bitmap = mImageCache.getBitmapFromDiskCache(dataString);
			}

			// If the bitmap was not found in the cache and this task has not
			// been cancelled by
			// another thread and the ImageView that was originally bound to
			// this task is still
			// bound back to this task and our "exit early" flag is not set,
			// then call the main
			// process method (as implemented by a subclass)
			if(isVcard && dataString!=null){
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
					
			        final File cacheDir = DiskLruCache.getDiskCacheDir(mContext, ImageFetcher.HTTP_CACHE_DIR);

			        final DiskLruCache cache =
			                DiskLruCache.openCache(mContext, cacheDir, ImageFetcher.HTTP_CACHE_SIZE);
//			        if (urlString.toUpperCase().startsWith("HTTP")) {
			        Log.e("������20130901������", "���cacheDir="+cacheDir+";cache="+cache+";dataString="+dataString);
			        if(cacheDir!=null && cache!=null){
			        final File cacheFile = new File(cache.createFilePath(dataString));//�ռ䲻�� cache=null

			        if (cache.containsKey(dataString)) {
//			            if (BuildConfig.DEBUG) {
////			                Log.d(TAG, "downloadBitmap - found in http cache - " + urlString);
//			            }
			        	return BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
			        }
			        }else{
//			        	Toast.makeText(mContext, "�洢�ռ䲻��", Toast.LENGTH_SHORT).show();
			        	Log.e("������20130901ImageWorker�洢�ռ䲻�������?", "���洢�ռ䲻��");
			        }
//			        if(xmppConnectionAdapter!=null)
//			        try{
//					vcard = xmppConnectionAdapter.getOtherVCard(StringUtils.parseName(dataString));
//					if(vcard!=null){
//						retbAvator = vcard.getAvatar();
//					    if(retbAvator!=null){
////					    	Log.e("������20130827������avator=",new String(retbAvator));
//					    	bitmap = BitmapFactory.decodeByteArray(retbAvator, 0, retbAvator.length);
//					    	if(cacheDir!=null && cache!=null)
//					    	cache.put(dataString, bitmap);
//					    	return bitmap;
//					    }
//					}
//			        }catch(Exception e){
//			        	
//			        }finally{
//			        	isVcard = false;
//			        	retbAvator = null;
//			        	vcard = null;
//			        	xmppConnectionAdapter = null;
//			        	
//			        }
				}
			}else{
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {

					bitmap = processBitmap(params[0]);

				}
			}
			
//			if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
//				bitmap = processBitmap(data);
//			}

			// If the bitmap was processed and the image cache is available,
			// then add the processed
			// bitmap to the cache for future use. Note we don't check if the
			// task was cancelled
			// here, if it was, and the thread is still running, we may as well
			// add the processed
			// bitmap to our cache as it might be used again in the future
			if (bitmap != null && mImageCache != null) {
				mImageCache.addBitmapToCache(dataString, bitmap);
			}

			return bitmap;
		}
//		@Override
//		protected void onProgressUpdate(Integer... progress) {
////			pd.setProgress((int) (progress[0]));
//			if(this.handler!=null){
//				android.os.Message message = this.handler.obtainMessage();
//				message.arg1 = (int) (progress[0]);
//				message.what = 1;
//	//								message.sendToTarget();
//				this.handler.sendMessage(message);
//			}
//		}
		/**
		 * Once the image is processed, associates it to the imageView
		 */
		@Override
		protected void onPostExecute(Bitmap bitmap) {
//			mSemaphore.release();
			// if cancel was called on this task or the "exit early" flag is set
			// then we're done
			if (isCancelled() || mExitTasksEarly) {
				bitmap = null;
			}

			final ImageView imageView = getAttachedImageView();
			if (bitmap != null && imageView != null) {
				
				//20130717 start
				
				int width = bitmap.getWidth();// ��ȡ��ʵ���?
				int height = bitmap.getHeight();

				LayoutParams lp = imageView.getLayoutParams();
//				if(uListype == 0){
//					lp.width = 77;//60
				if(mSizeType==0){
					lp.width = dip2px(mContext,77);
//					lp.height = 77;//60	
					lp.height = dip2px(mContext,77);
				}else if(mSizeType==1){
					lp.width = dip2px(mContext,mWid);
//					lp.height = 77;//60	
					lp.height = dip2px(mContext,mHeig);
				}else{
					lp.width = mSizeType;
//					lp.height = 77;//60	
					lp.height = mSizeType;
				}
//				}else{
//				    lp.width = imageView.getItemWidth();
////					lp.height = (height * imageView.getItemWidth())
////							/ width;// ����߶�?
//					lp.height = getHeight(imageView.getItemWidth(),height,width);
//				}
				
				imageView.setLayoutParams(lp);
				//20130717 end
				
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				if(mSizeType==0)
					setImageBitmapNormalImage(imageView, PhotoUtils.toRoundCorner(bitmap, 8));
				else
					setImageBitmapNormalImage(imageView, bitmap);
			}
			if(this.handler!=null)
				this.handler.sendEmptyMessage(2);
		}

		/**
		 * Returns the ImageView associated with this task as long as the
		 * ImageView's task still points to this task as well. Returns null
		 * otherwise.
		 */
		private ImageView getAttachedImageView() {
			final ImageView imageView = imageViewReference.get();
			final BitmapWorkerNormalImageTask bitmapWorkerTask = getBitmapWorkerNormalImageTask(imageView);

			if (this == bitmapWorkerTask) {
				return imageView;
			}

			return null;
		}
		
		public int getHeight(int srcViewWidth,int srcHeight,int srcWidth){
			int defHeight = 77;
			Random random = new Random();
			return (srcHeight * srcViewWidth) / srcWidth + random.nextInt(3)*10;
		}
	}
	protected List<AsyncTask<Object, Integer, Bitmap>> mAsyncTasks_RoundImage = new ArrayList<AsyncTask<Object, Integer, Bitmap>>();	
	protected void putAsyncTask_RoundImage(AsyncTask<Object, Integer, Bitmap> asyncTask,Object data) {
		mAsyncTasks_RoundImage.add(asyncTask.executeOnExecutor(LIMITED_TASK_EXECUTOR, data));//LIMITED_TASK_EXECUTOR  FULL_TASK_EXECUTOR
//		mAsyncTasks.add(asyncTask.execute());
	}
	protected void clearAsyncTask_RoundImage() {
		Iterator<AsyncTask<Object, Integer, Bitmap>> iterator = mAsyncTasks_RoundImage.iterator();
		while (iterator.hasNext()) {
			AsyncTask<Object, Integer, Bitmap> asyncTask = iterator.next();
			if (asyncTask != null && !asyncTask.isCancelled()) {
				asyncTask.cancel(true);
			}
		}
		mAsyncTasks_RoundImage.clear();
	}
	public void onCancel_RoundImage() {
		clearAsyncTask_RoundImage();
	}
	private class BitmapWorkerRoundImageViewTask extends AsyncTask<Object, Integer, Bitmap> {//Void ----> Integer
		private Object data;
		private Handler handler;
		private final WeakReference<RoundImageView> imageViewReference;

		public BitmapWorkerRoundImageViewTask(RoundImageView imageView,Handler handler) {
			imageViewReference = new WeakReference<RoundImageView>(imageView);
			this.handler = handler;
		}
		
//		public BitmapWorkerTask(FlowView imageView,Object data1){
//			imageViewReference = new WeakReference<FlowView>(imageView);
//			data = data1;
//		}

		/**
		 * Background processing.
		 */
		@Override
		protected Bitmap doInBackground(Object... params) {
			data = params[0];
			final String dataString = String.valueOf(data);
			Bitmap bitmap = null;

			// If the image cache is available and this task has not been
			// cancelled by another
			// thread and the ImageView that was originally bound to this task
			// is still bound back
			// to this task and our "exit early" flag is not set then try and
			// fetch the bitmap from
			// the cache
			if (mImageCache != null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
				bitmap = mImageCache.getBitmapFromDiskCache(dataString);
			}

			// If the bitmap was not found in the cache and this task has not
			// been cancelled by
			// another thread and the ImageView that was originally bound to
			// this task is still
			// bound back to this task and our "exit early" flag is not set,
			// then call the main
			// process method (as implemented by a subclass)
			if(isVcard && dataString!=null){
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
					
			        final File cacheDir = DiskLruCache.getDiskCacheDir(mContext, ImageFetcher.HTTP_CACHE_DIR);

			        final DiskLruCache cache =
			                DiskLruCache.openCache(mContext, cacheDir, ImageFetcher.HTTP_CACHE_SIZE);
//			        if (urlString.toUpperCase().startsWith("HTTP")) {
			        Log.e("������20130901������", "���cacheDir="+cacheDir+";cache="+cache+";dataString="+dataString);
			        if(cacheDir!=null && cache!=null){
			        final File cacheFile = new File(cache.createFilePath(dataString));//�ռ䲻�� cache=null

			        if (cache.containsKey(dataString)) {
//			            if (BuildConfig.DEBUG) {
////			                Log.d(TAG, "downloadBitmap - found in http cache - " + urlString);
//			            }
			        	return BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
			        }
			        }else{
//			        	Toast.makeText(mContext, "�洢�ռ䲻��", Toast.LENGTH_SHORT).show();
			        	Log.e("������20130901ImageWorker�洢�ռ䲻�������?", "���洢�ռ䲻��");
			        }
//			        if(xmppConnectionAdapter!=null)
//			        try{
//					vcard = xmppConnectionAdapter.getOtherVCard(StringUtils.parseName(dataString));
//					if(vcard!=null){
//						retbAvator = vcard.getAvatar();
//					    if(retbAvator!=null){
////					    	Log.e("������20130827������avator=",new String(retbAvator));
//					    	bitmap = BitmapFactory.decodeByteArray(retbAvator, 0, retbAvator.length);
//					    	if(cacheDir!=null && cache!=null)
//					    	cache.put(dataString, bitmap);
//					    	return bitmap;
//					    }
//					}
//			        }catch(Exception e){
//			        	
//			        }finally{
//			        	isVcard = false;
//			        	retbAvator = null;
//			        	vcard = null;
//			        	xmppConnectionAdapter = null;
//			        	
//			        }
				}
			}else{
				if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {

					bitmap = processBitmap(params[0]);

				}
			}
			
//			if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) {
//				bitmap = processBitmap(data);
//			}

			// If the bitmap was processed and the image cache is available,
			// then add the processed
			// bitmap to the cache for future use. Note we don't check if the
			// task was cancelled
			// here, if it was, and the thread is still running, we may as well
			// add the processed
			// bitmap to our cache as it might be used again in the future
			if (bitmap != null && mImageCache != null) {
				mImageCache.addBitmapToCache(dataString, bitmap);
			}

			return bitmap;
		}
		@Override
		protected void onProgressUpdate(Integer... progress) {
//			pd.setProgress((int) (progress[0]));
			if(this.handler!=null){
				android.os.Message message = this.handler.obtainMessage();
				message.arg1 = (int) (progress[0]);
				message.what = 1;
	//								message.sendToTarget();
				this.handler.sendMessage(message);
			}
		}
		/**
		 * Once the image is processed, associates it to the imageView
		 */
		@Override
		protected void onPostExecute(Bitmap bitmap) {
//			mSemaphore.release();
			// if cancel was called on this task or the "exit early" flag is set
			// then we're done
			if (isCancelled() || mExitTasksEarly) {
				bitmap = null;
			}

			final RoundImageView imageView = getAttachedImageView();
			if (bitmap != null && imageView != null) {
				
				//20130717 start
				
				int width = bitmap.getWidth();// ��ȡ��ʵ���?
				int height = bitmap.getHeight();

				LayoutParams lp = imageView.getLayoutParams();
//				if(uListype == 0){
//				lp.width = 77;//60
				lp.width = dip2px(mContext,77);
//				lp.height = 77;//60	
				lp.height = dip2px(mContext,77);
//				}else{
//					lp.height = (height * imageView.getItemWidth())
//							/ width;// ����߶�?
//				}
				
				imageView.setLayoutParams(lp);
				//20130717 end
				
//				bd = (BitmapDrawable) asyncDrawable;
//				bitmap = bd.getBitmap();
//				imageView.setImageBitmap(PhotoUtils.toRoundCorner(bitmap, 3));
				setImageBitmapRoundImageView(imageView, PhotoUtils.toRoundCorner(bitmap, 8));
			}
			if(this.handler!=null)
			this.handler.sendEmptyMessage(2);
		}

		/**
		 * Returns the ImageView associated with this task as long as the
		 * ImageView's task still points to this task as well. Returns null
		 * otherwise.
		 */
		private RoundImageView getAttachedImageView() {
			final RoundImageView imageView = imageViewReference.get();
			final BitmapWorkerRoundImageViewTask bitmapWorkerTask = getBitmapWorkerRoundImageViewTask(imageView);

			if (this == bitmapWorkerTask) {
				return imageView;
			}

			return null;
		}
	}
	/**
	 * A custom Drawable that will be attached to the imageView while the work
	 * is in progress. Contains a reference to the actual worker task, so that
	 * it can be stopped if a new binding is required, and makes sure that only
	 * the last started worker process can bind its result, independently of the
	 * finish order.
	 */
	private static class AsyncDrawable extends BitmapDrawable {
		private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;

		public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
			super(res, bitmap);

			bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
		}

		public BitmapWorkerTask getBitmapWorkerTask() {
			return bitmapWorkerTaskReference.get();
		}
	}
	private static class AsyncDrawableNormalImage extends BitmapDrawable {
		private final WeakReference<BitmapWorkerNormalImageTask> bitmapWorkerTaskReference;

		public AsyncDrawableNormalImage(Resources res, Bitmap bitmap, BitmapWorkerNormalImageTask bitmapWorkerTask) {
			super(res, bitmap);

			bitmapWorkerTaskReference = new WeakReference<BitmapWorkerNormalImageTask>(bitmapWorkerTask);
		}

		public BitmapWorkerNormalImageTask getBitmapWorkerNormalImageTask() {
			return bitmapWorkerTaskReference.get();
		}
	}	
	private static class AsyncDrawableRoundImageView extends BitmapDrawable {
		private final WeakReference<BitmapWorkerRoundImageViewTask> bitmapWorkerTaskReference;

		public AsyncDrawableRoundImageView(Resources res, Bitmap bitmap, BitmapWorkerRoundImageViewTask bitmapWorkerTask) {
			super(res, bitmap);

			bitmapWorkerTaskReference = new WeakReference<BitmapWorkerRoundImageViewTask>(bitmapWorkerTask);
		}

		public BitmapWorkerRoundImageViewTask getBitmapWorkerTask() {
			return bitmapWorkerTaskReference.get();
		}
	}

	/**
	 * Called when the processing is complete and the final bitmap should be set
	 * on the ImageView.
	 * 
	 * @param imageView
	 * @param bitmap
	 */
	private void setImageBitmap(FlowView imageView, Bitmap bitmap) {
		if (mFadeInBitmap) {
			// Transition drawable with a transparent drwabale and the final
			// bitmap
			final TransitionDrawable td = new TransitionDrawable(new Drawable[] { new ColorDrawable(android.R.color.transparent),
					new BitmapDrawable(mContext.getResources(), bitmap) });
			// Set background to loading bitmap
			imageView.setBackgroundDrawable(new BitmapDrawable(mContext.getResources(), mLoadingBitmap));

			imageView.setImageDrawable(td);
			td.startTransition(FADE_IN_TIME);
		} else {
			imageView.setImageBitmap(bitmap);
		}
	}
	private void setImageBitmapNormalImage(ImageView imageView, Bitmap bitmap) {
		if (mFadeInBitmap) {
			// Transition drawable with a transparent drwabale and the final
			// bitmap
			final TransitionDrawable td = new TransitionDrawable(new Drawable[] { new ColorDrawable(android.R.color.transparent),
					new BitmapDrawable(mContext.getResources(), bitmap) });
			// Set background to loading bitmap
			imageView.setBackgroundDrawable(new BitmapDrawable(mContext.getResources(), mLoadingBitmap));

			imageView.setImageDrawable(td);
			td.startTransition(FADE_IN_TIME);
		} else {
			imageView.setImageBitmap(bitmap);
		}
	}
	private void setImageBitmapRoundImageView(RoundImageView imageView, Bitmap bitmap) {
		if (mFadeInBitmap) {
			// Transition drawable with a transparent drwabale and the final
			// bitmap
			final TransitionDrawable td = new TransitionDrawable(new Drawable[] { new ColorDrawable(android.R.color.transparent),
					new BitmapDrawable(mContext.getResources(), bitmap) });
			// Set background to loading bitmap
			imageView.setBackgroundDrawable(new BitmapDrawable(mContext.getResources(), mLoadingBitmap));

			imageView.setImageDrawable(td);
			td.startTransition(FADE_IN_TIME);
		} else {
			imageView.setImageBitmap(bitmap);
		}
	}
	/**
	 * Set the simple adapter which holds the backing data.
	 * 
	 * @param adapter
	 */
	public void setAdapter(ImageWorkerAdapter adapter) {
		mImageWorkerAdapter = adapter;
	}

	/**
	 * Get the current adapter.
	 * 
	 * @return
	 */
	public ImageWorkerAdapter getAdapter() {
		return mImageWorkerAdapter;
	}

	/**
	 * A very simple adapter for use with ImageWorker class and subclasses.
	 */
	public static abstract class ImageWorkerAdapter {
		public abstract Object getItem(int num);

		public abstract int getSize();
	}
	
	public static int dip2px(Context context, float dipValue){ 
        final float scale = context.getResources().getDisplayMetrics().density; 
        return (int)(dipValue * scale + 0.5f); 
	} 
	
	public static int px2dip(Context context, float pxValue){ 
	        final float scale = context.getResources().getDisplayMetrics().density; 
	        return (int)(pxValue / scale + 0.5f); 
	} 
}
